home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _F1EF4D28435642599E0B7C36BF13895F < prev    next >
Encoding:
Text File  |  2002-06-15  |  36.3 KB  |  1,453 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // cg_gore.c -- handle client-side gore
  4.  
  5. #include "cg_local.h"
  6. #if !defined(GHOUL2_SHARED_H_INC)
  7. #include "..\ghoul2\G2_gore_shared.h"
  8. #endif
  9.  
  10.  
  11. void CG_AddGore(int type, float size, vec3_t hitloc, vec3_t hitdirection, 
  12.                 int entnum, vec3_t entposition, float entangle, void *ghoul2)
  13. {
  14.     SSkinGoreData goreSkin;
  15.  
  16.     memset ( &goreSkin, 0, sizeof(goreSkin) );
  17.  
  18.     goreSkin.growDuration = -1; // default expandy time
  19.     goreSkin.goreScaleStartFraction = 1.0; // default start scale
  20.     goreSkin.frontFaces = qtrue; // forever
  21.     goreSkin.backFaces = qtrue; // forever
  22.     goreSkin.lifeTime = 0;
  23.     goreSkin.baseModelOnly = qfalse;
  24.     
  25.     goreSkin.currentTime = cg.time;
  26.     goreSkin.entNum      = entnum;
  27.     goreSkin.SSize         = size;
  28.     goreSkin.TSize         = size;
  29.     goreSkin.theta         = flrand(0,6.28);
  30.     goreSkin.shaderEnum  = type;
  31.  
  32.     VectorSet ( goreSkin.scale, 1, 1, 1 );
  33.  
  34.     VectorCopy ( hitdirection, goreSkin.rayDirection);
  35.  
  36.     VectorCopy ( hitloc, goreSkin.hitLocation );
  37.     VectorCopy ( entposition, goreSkin.position );
  38.     goreSkin.angles[YAW] = entangle;
  39.  
  40.     trap_G2API_AddSkinGore(ghoul2,&goreSkin);
  41. }
  42.  
  43. void CG_AddGrowGore(int type, float size, int growtime, float startfrac, vec3_t hitloc, vec3_t hitdirection,
  44.                 int entnum, vec3_t entposition, float entangle, void *ghoul2)
  45. {
  46.     SSkinGoreData goreSkin;
  47.  
  48.     memset ( &goreSkin, 0, sizeof(goreSkin) );
  49.  
  50.     goreSkin.frontFaces = qtrue; // forever
  51.     goreSkin.backFaces = qtrue; // forever
  52.     goreSkin.lifeTime = 0;
  53.     goreSkin.baseModelOnly = qfalse;
  54.     
  55.     goreSkin.currentTime = cg.time;
  56.     goreSkin.entNum      = entnum;
  57.     goreSkin.SSize         = size;
  58.     goreSkin.TSize         = size;
  59.     goreSkin.theta         = flrand(0,6.28);
  60.     goreSkin.shaderEnum  = type;
  61.     goreSkin.growDuration = growtime; // default expandy time
  62.     goreSkin.goreScaleStartFraction = startfrac; // default start scale
  63.  
  64.     VectorSet ( goreSkin.scale, 1, 1, 1 );
  65.  
  66.     VectorCopy ( hitdirection, goreSkin.rayDirection);
  67.  
  68.     VectorCopy ( hitloc, goreSkin.hitLocation );
  69.     VectorCopy ( entposition, goreSkin.position );
  70.     goreSkin.angles[YAW] = entangle;
  71.  
  72.     trap_G2API_AddSkinGore(ghoul2,&goreSkin);
  73. }
  74.  
  75. void CG_AddSlashGore(int type, float angle, float ssize, float tsize, vec3_t hitloc, vec3_t hitdirection, 
  76.                      int entnum, vec3_t entposition, float entangle, void *ghoul2)
  77. {
  78.     SSkinGoreData goreSkin;
  79.  
  80.     memset ( &goreSkin, 0, sizeof(goreSkin) );
  81.  
  82.     goreSkin.growDuration = -1; // default expandy time
  83.     goreSkin.goreScaleStartFraction = 1.0; // default start scale
  84.     goreSkin.frontFaces = qtrue; // forever
  85.     goreSkin.backFaces = qtrue; // forever
  86.     goreSkin.lifeTime = 0;
  87.     goreSkin.baseModelOnly = qfalse;
  88.  
  89.     goreSkin.currentTime = cg.time;
  90.     goreSkin.entNum      = entnum;
  91.     goreSkin.SSize         = ssize;
  92.     goreSkin.TSize         = tsize;
  93.     goreSkin.theta         = angle;
  94.     goreSkin.shaderEnum  = type;
  95.  
  96.     VectorSet ( goreSkin.scale, 1, 1, 1 );
  97.  
  98.     VectorCopy ( hitdirection, goreSkin.rayDirection);
  99.  
  100.     VectorCopy ( hitloc, goreSkin.hitLocation );
  101.     VectorCopy ( entposition, goreSkin.position );
  102.     goreSkin.angles[YAW] = entangle;
  103.  
  104.     trap_G2API_AddSkinGore(ghoul2,&goreSkin);
  105. }
  106.  
  107. void CG_AddSlashGrowGore(int type, float angle, float ssize, float tsize, int growtime, float startfrac, 
  108.                             vec3_t hitloc, vec3_t hitdirection, 
  109.                             int entnum, vec3_t entposition, float entangle, void *ghoul2)
  110. {
  111.     SSkinGoreData goreSkin;
  112.  
  113.     memset ( &goreSkin, 0, sizeof(goreSkin) );
  114.  
  115.     goreSkin.frontFaces = qtrue; // forever
  116.     goreSkin.backFaces = qtrue; // forever
  117.     goreSkin.lifeTime = 0;
  118.     goreSkin.baseModelOnly = qfalse;
  119.  
  120.     goreSkin.growDuration = growtime; // default expandy time
  121.     goreSkin.goreScaleStartFraction = startfrac; // default start scale
  122.     goreSkin.currentTime = cg.time;
  123.     goreSkin.entNum      = entnum;
  124.     goreSkin.SSize         = ssize;
  125.     goreSkin.TSize         = tsize;
  126.     goreSkin.theta         = angle;
  127.     goreSkin.shaderEnum  = type;
  128.  
  129.     VectorSet ( goreSkin.scale, 1, 1, 1 );
  130.  
  131.     VectorCopy ( hitdirection, goreSkin.rayDirection);
  132.  
  133.     VectorCopy ( hitloc, goreSkin.hitLocation );
  134.     VectorCopy ( entposition, goreSkin.position );
  135.     goreSkin.angles[YAW] = entangle;
  136.  
  137.     trap_G2API_AddSkinGore(ghoul2,&goreSkin);
  138. }
  139.  
  140.  
  141. void CG_AddTimedGore(int type, float size, int duration, vec3_t hitloc, vec3_t hitdirection, 
  142.                     int entnum, vec3_t entposition, float entangle, void *ghoul2)
  143. {
  144.     SSkinGoreData goreSkin;
  145.  
  146.     memset ( &goreSkin, 0, sizeof(goreSkin) );
  147.  
  148.     goreSkin.growDuration = -1; // default expandy time
  149.     goreSkin.goreScaleStartFraction = 1.0; // default start scale
  150.     goreSkin.frontFaces = qtrue; // forever
  151.     goreSkin.backFaces = qtrue; // forever
  152.     goreSkin.baseModelOnly = qfalse;
  153.  
  154.     goreSkin.currentTime = cg.time;
  155.     goreSkin.entNum      = entnum;
  156.     goreSkin.SSize         = size;
  157.     goreSkin.TSize         = size;
  158.     goreSkin.theta         = flrand(0,6.28);
  159.     goreSkin.shaderEnum  = type;
  160.     goreSkin.lifeTime     = duration;
  161.  
  162.     VectorSet ( goreSkin.scale, 1, 1, 1 );
  163.  
  164.     VectorCopy ( hitdirection, goreSkin.rayDirection);
  165.  
  166.     VectorCopy ( hitloc, goreSkin.hitLocation );
  167.     VectorCopy ( entposition, goreSkin.position );
  168.     goreSkin.angles[YAW] = entangle;
  169.  
  170.     trap_G2API_AddSkinGore(ghoul2,&goreSkin);
  171. }
  172.  
  173.  
  174. void CG_DoGoreFromWeapon( int weaponnum, int attack, vec3_t hitloc, vec3_t hitdirection, 
  175.                          int entnum, vec3_t entposition, float entangle, void *ghoul2)
  176. {
  177.     float angle, size, size2;
  178.  
  179.     switch (weaponnum)
  180.     {
  181.     case WP_KNIFE:
  182.         if (attack==ATTACK_ALTERNATE)
  183.         {
  184.             CG_AddGore(PGORE_PUNCTURE, flrand(3.5, 4.0), 
  185.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  186.             if (cg_goreDetail.integer>0)
  187.             {
  188.                 CG_AddGrowGore(PGORE_KNIFE_SOAK, 4.0*1.4, 15000, 0.1,
  189.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  190.             }
  191.         }
  192.         else
  193.         {
  194.             angle= (M_PI / 2 * (1+2*irand(0,1))) + flrand( .7, .7);
  195.             switch(irand(1,3))
  196.             {
  197.             case 1:
  198.                 size = flrand(2.8, 3.2);
  199.                 size2 = flrand(1.8, 2.2);
  200.                 CG_AddSlashGore(PGORE_KNIFESLASH, 
  201.                         angle, size, size2, 
  202.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  203.                 if (cg_goreDetail.integer>0)
  204.                 {
  205.                     CG_AddSlashGrowGore(PGORE_KNIFE_SOAK, angle, size*1.2, size2*2.0, 15000, 0.1,
  206.                                 hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  207.                 }
  208.                 break;
  209.             case 2:
  210.                 size = 8.0f*flrand(.8, 1.2);
  211.                 size2 = 1.75f*flrand(.8, 1.2);
  212.                 CG_AddSlashGore(PGORE_KNIFESLASH2, 
  213.                         angle, size, size2, 
  214.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  215.                 if (cg_goreDetail.integer>0)
  216.                 {
  217.                     CG_AddSlashGrowGore(PGORE_KNIFE_SOAK, angle, size*1.2, size2*2.0, 15000, 0.1,
  218.                                 hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  219.                 }
  220.                 break;
  221.             default:
  222.                 size = flrand(3.0f,4.0f);
  223.                 size2 = flrand(0.5f,1.0f);
  224.                 CG_AddSlashGore(PGORE_KNIFESLASH3, 
  225.                         angle, size, size2, 
  226.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  227.                 if (cg_goreDetail.integer>0)
  228.                 {
  229.                     CG_AddSlashGrowGore(PGORE_KNIFE_SOAK, angle, size*1.2, size2*2.0, 15000, 0.1,
  230.                                 hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  231.                 }
  232.                 break;
  233.             }
  234.         }
  235.         break;
  236.  
  237.     // Smaller guns with pistol whip altfires
  238.     case WP_M1911A1_PISTOL:
  239.     case WP_USSOCOM_PISTOL:
  240.         if (attack==ATTACK_ALTERNATE)
  241.         {    // Bonk on the head
  242.             CG_AddGore(PGORE_BLOODY_SPLOTCH2, flrand(5.25f, 7.5f), 
  243.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  244.  
  245.         }
  246.         else
  247.         {
  248.             CG_AddGore(irand(PGORE_BULLET_E, PGORE_BULLET_G), flrand( 3.75f, 4.5f), 
  249.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  250.             if (cg_goreDetail.integer>0)
  251.             {
  252.                 CG_AddGrowGore(PGORE_KNIFE_SOAK, 4.5*1.35, 15000, 0.1f,
  253.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  254.             }
  255.         }
  256.         break;
  257.  
  258.     // Small guns
  259.     case WP_MICRO_UZI_SUBMACHINEGUN:
  260.         CG_AddGore(irand(PGORE_BULLET_E, PGORE_BULLET_G), flrand( 3.75f, 4.5f), 
  261.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  262.         if (cg_goreDetail.integer>0)
  263.         {
  264.             CG_AddGrowGore(PGORE_KNIFE_SOAK, 4.5f*1.35f, 15000, 0.1f,
  265.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  266.         }
  267.         break;
  268.  
  269.     // Shotgun with whip altfire
  270.     case WP_M590_SHOTGUN:
  271.         if (attack==ATTACK_ALTERNATE)
  272.         {    // Bond on de haid
  273.             CG_AddGore(PGORE_BLOODY_SPLOTCH2, flrand(7.75, 11.25), 
  274.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  275.         }
  276.         else
  277.         {
  278.             CG_AddGore(irand(PGORE_SHOTGUN, PGORE_SHOTGUNBIG), flrand( 8.25f, 11.25f), 
  279.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  280.             if (cg_goreDetail.integer>0)
  281.             {
  282.                 CG_AddGrowGore(PGORE_KNIFE_SOAK, 11.25f*1.25f, 15000, 0.1f,
  283.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  284.                 if (cg_goreDetail.integer>1)
  285.                 {
  286.                     CG_AddGore(PGORE_PELLETS, 8.25f, 
  287.                                     hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  288.                 }
  289.             }
  290.         }
  291.         break;
  292.  
  293.     // Medium guns
  294.     case WP_M3A1_SUBMACHINEGUN:
  295.     case WP_MP5:
  296.         CG_AddGore(irand(PGORE_BULLET_E, PGORE_BULLET_G), flrand( 5.25f, 7.5f), 
  297.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  298.         if (cg_goreDetail.integer>0)
  299.         {
  300.             CG_AddGrowGore(PGORE_KNIFE_SOAK, 7.5f*1.3f, 15000, 0.1f,
  301.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  302.         }
  303.         break;
  304.  
  305.     // Shotguns
  306.     case WP_USAS_12_SHOTGUN:
  307.         CG_AddGore(irand(PGORE_SHOTGUN, PGORE_SHOTGUNBIG), flrand( 8.25f, 11.25f), 
  308.                     hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  309.         if (cg_goreDetail.integer>0)
  310.         {
  311.             CG_AddGrowGore(PGORE_KNIFE_SOAK, 11.25f*1.25f, 15000, 0.1,
  312.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  313.             if (cg_goreDetail.integer>1)
  314.             {
  315.                 CG_AddGore(PGORE_PELLETS, 8.25f, 
  316.                                 hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  317.             }
  318.         }
  319.         break;
  320.  
  321.     // Assault rifle with grenade altfire
  322.     case WP_M4_ASSAULT_RIFLE:
  323.         if (attack==ATTACK_ALTERNATE)
  324.         {
  325.             CG_AddGore(PGORE_SHRAPNEL, flrand( 14.0f, 17.0f),  
  326.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  327.             if (cg_goreDetail.integer>1)
  328.             {
  329.                 CG_AddGore(PGORE_PELLETS, 10.0, 
  330.                                 hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  331.             }
  332.         }
  333.         else
  334.         {
  335.             CG_AddGore(irand(PGORE_BULLET_E, PGORE_BULLET_G), flrand( 5.25f, 7.5f), 
  336.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  337.             if (cg_goreDetail.integer>0)
  338.             {
  339.                 CG_AddGrowGore(PGORE_KNIFE_SOAK, 7.5f*1.3f, 15000, 0.1f,
  340.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  341.             }
  342.         }
  343.         break;
  344.  
  345.     // Assault rifle with bayonet altfire
  346.     case WP_AK74_ASSAULT_RIFLE:
  347.         if (attack==ATTACK_ALTERNATE)
  348.         {
  349.             CG_AddGore(PGORE_PUNCTURE, flrand(3.5f, 4.0f), 
  350.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  351.             if (cg_goreDetail.integer>0)
  352.             {
  353.                 CG_AddGrowGore(PGORE_KNIFE_SOAK, 4.0f*1.4f, 15000, 0.1f,
  354.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  355.             }
  356.         }
  357.         else
  358.         {
  359.             CG_AddGore(irand(PGORE_BULLET_E, PGORE_BULLET_G), flrand( 5.25f, 7.5f), 
  360.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  361.             if (cg_goreDetail.integer>0)
  362.             {
  363.                 CG_AddGrowGore(PGORE_KNIFE_SOAK, 7.5f*1.3f, 15000, 0.1f,
  364.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  365.             }
  366.         }
  367.         break;
  368.  
  369.     // Large-caliber bullets
  370.     case WP_MSG90A1:
  371.     case WP_M60_MACHINEGUN:
  372.         CG_AddGore(irand(PGORE_BULLET_E, PGORE_BULLET_G), flrand( 6.0f, 9.0f),
  373.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  374.         if (cg_goreDetail.integer>0)
  375.         {
  376.             CG_AddGrowGore(PGORE_KNIFE_SOAK, 9.0f*1.25f, 15000, 0.1f,
  377.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  378.         }
  379.         break;
  380.  
  381.     // Explosions
  382.     case WP_MM1_GRENADE_LAUNCHER:
  383.     case WP_RPG7_LAUNCHER:
  384.     case WP_SMOHG92_GRENADE:
  385.         CG_AddGore(PGORE_SHRAPNEL, flrand( 14.0f, 17.0f),  
  386.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  387.         if (cg_goreDetail.integer>1)
  388.         {
  389.             CG_AddGore(PGORE_PELLETS, 10.0f, 
  390.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  391.         }
  392.         break;
  393.  
  394.     // Stun/char
  395.     case WP_M84_GRENADE:
  396.     case WP_M15_GRENADE:
  397.         CG_AddGore(PGORE_BURN, flrand( 14.0f, 18.0f),  
  398.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  399.         break;
  400.  
  401.     // Fire
  402.     case WP_ANM14_GRENADE:
  403.         CG_AddTimedGore(PGORE_IMMOLATE, flrand( 18.0f, 22.0f), 4000, 
  404.                         hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  405.         if (cg_goreDetail.integer>0)
  406.         {
  407.             CG_AddGore(PGORE_BURN, flrand( 18.0f, 22.0f),  
  408.                             hitloc, hitdirection, entnum, entposition, entangle, ghoul2);
  409.         }
  410.         break;
  411.     }
  412. }
  413.  
  414.  
  415. void CG_PredictedProcGore ( int weaponnum, int attack, vec3_t start, vec3_t end, centity_t* cent )
  416. {
  417.     vec3_t direction;
  418.  
  419.     // if no blood then dont add the proc gore
  420.     if ( cg_lockBlood.integer || !cent->ghoul2 || !cent->currentValid)
  421.     {
  422.         return;
  423.     }
  424.     
  425.     VectorSubtract ( end, start, direction);
  426.     VectorNormalize ( direction);
  427.  
  428.     CG_DoGoreFromWeapon(weaponnum, attack,                // Weaponnum and altattack
  429.             end, direction,                                // hitloc and hitdirection
  430.             cent->currentState.number,                    // victim entity number
  431.             cent->lerpOrigin, cent->pe.ghoulLegsAngles[YAW],    // entity position, entity yaw
  432.             cent->ghoul2);
  433. }
  434.  
  435. /*
  436. ======================
  437. CG_AddProcGore
  438.  
  439. Adds procedural gore to the player specified in the given cent.  The cent is a 
  440. temp ent containing all the information about the shot.
  441. ======================
  442. */
  443. void CG_AddProcGore(centity_t *cent)
  444. {
  445.     centity_t*      source;
  446.     attackType_t  attack;
  447.     vec3_t          direction;
  448.  
  449.     // Blood locked?
  450.     if ( cg_lockBlood.integer || !cent->currentState.time )
  451.     {
  452.         return;
  453.     }
  454.  
  455.     // No procedural gore on this shot.
  456.     if ( cent->currentState.time & GORE_NONE )
  457.     {
  458.         return;
  459.     }
  460.  
  461.     source = CG_GetEntity ( cent->currentState.otherEntityNum2 );
  462.     if (!source->ghoul2 || !source->currentValid)
  463.     {
  464.         return;
  465.     }
  466.  
  467.     // Extract the direction of fire
  468.     ByteToDir( cent->currentState.eventParm, direction );
  469.     attack = ((cent->currentState.time>>8)&0xFF);
  470.  
  471.     CG_UpdatePlayerModel ( source );
  472.  
  473.     CG_DoGoreFromWeapon(cent->currentState.time&0xFF, attack,                    // Weaponnum and altattack
  474.             cent->lerpOrigin, direction,                                // hitloc and hitdirection
  475.             cent->currentState.otherEntityNum2,                                    // victim entity number
  476.             cent->currentState.angles, (cent->currentState.time>>16)&0x7FFF,                // entity position, entity yaw
  477.             source->ghoul2);
  478. }
  479.  
  480.  
  481.  
  482. #define MAX_GORE_POOL    20000
  483.  
  484. static char        gorePool[MAX_GORE_POOL];
  485. static int        gorePoolSize = 0;
  486.  
  487. static char *AllocGorePool(int size)
  488. {
  489.     gorePoolSize = ((gorePoolSize + 0x00000003) & 0xfffffffc);
  490.  
  491.     if (gorePoolSize + size > MAX_GORE_POOL)
  492.     {
  493.         Com_Error( ERR_DROP, "AllocGorePool: buffer exceeded (%d > %d)", gorePoolSize + size, MAX_GORE_POOL);
  494.         return 0;
  495.     }
  496.  
  497.     gorePoolSize += size;
  498.  
  499.     return &gorePool[gorePoolSize-size];
  500. }
  501.  
  502. static char *AllocMultiString(TGPValue field)
  503. {
  504.     TGPValue    value;
  505.     int            size = 1;
  506.     char        name[256];
  507.     char        *output, *pos;
  508.  
  509.     if (!field)
  510.     {
  511.         return 0;
  512.     }
  513.  
  514.     value = trap_GPV_GetList(field);
  515.     while(value)
  516.     {
  517.         trap_GPV_GetName(value, name);
  518.         size += strlen(name) + 1;
  519.         value = trap_GPV_GetNext(value);
  520.     }
  521.  
  522.     output = pos = AllocGorePool(size);
  523.     value = trap_GPV_GetList(field);
  524.     while(value)
  525.     {
  526.         trap_GPV_GetName(value, name);
  527.         strcpy(pos, name);
  528.         pos += strlen(name) + 1;
  529.         value = trap_GPV_GetNext(value);
  530.     }
  531.     *pos = 0;
  532.  
  533.     return output;
  534. }
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541.  
  542.  
  543. #define    GORE_CHILD                        0x00000001
  544. #define    GORE_NO_CHILD_SURFACES_ON        0x00000002
  545. #define GORE_NO_CHILD_FX                0x00000004
  546. #define GORE_NO_CHILD_CHUNKS            0x00000008
  547. #define GORE_NO_CHILD_BOLTONS            0x00000010
  548.  
  549. typedef enum
  550. {
  551.     GORE_SIDE_RIGHT = 0,
  552.     GORE_SIDE_LEFT,
  553.     GORE_SIDE_MAX
  554. } EGoreSide;
  555.  
  556. typedef struct SGoreInfo
  557. {
  558.     const char    *mLongName;
  559.     const char    *mShortName;
  560. } TGoreInfo;
  561.  
  562. typedef struct SGoreLocation
  563. {
  564.     const char    *mPublicName;
  565.     EGoreSide    mPrimarySide;
  566.     EGoreSide    mOppositeSide;
  567. } TGoreLocation;
  568.  
  569. typedef struct SGoreEffectType
  570. {
  571.     char            mName[MAX_QPATH];
  572.     int                mFXID;
  573.  
  574.     struct SGoreEffectType    *mNext;
  575. } TGoreEffectType;
  576.  
  577. typedef struct SGorePieceType
  578. {
  579.     char            mName[MAX_QPATH];
  580.     char            mBolt[MAX_QPATH];
  581.  
  582.     TGhoul2            mG2Model;
  583.     qhandle_t        mNormalModel;
  584.  
  585.     struct SGorePieceType    *mNext;
  586. } TGorePieceType;
  587.  
  588. typedef struct SGoreEffect
  589. {
  590.     char            mName[MAX_QPATH];
  591.     char            mBolt[MAX_QPATH];
  592.  
  593.     struct SGoreEffect        *mNext;
  594. } TGoreEffect;
  595.  
  596. typedef struct SGoreBoltOn
  597. {
  598.     char            mName[MAX_QPATH];
  599.     char            mBolt[MAX_QPATH];
  600.  
  601.     struct SGoreBoltOn        *mNext;
  602. } TGoreBoltOn;
  603.  
  604. typedef struct SGoreChunk
  605. {
  606.     char            mRoot[MAX_QPATH];
  607.     char            mBone[MAX_QPATH];
  608.     char            *mSurfacesOn;
  609.     char            *mChildrenOff;
  610.     float            mMinForce;
  611.     float            mMaxForce;
  612.  
  613.     struct SGoreChunk        *mNext;
  614. } TGoreChunk;
  615.  
  616. typedef struct SGoreArea
  617. {
  618.     char            mLocation[MAX_QPATH];
  619.     char            *mSurfacesOff;
  620.     char            *mSurfacesOn;
  621.     char            *mBoltsOff;
  622.     char            *mChildren;
  623.     unsigned        mFlags;
  624.  
  625.     struct SGoreEffect        *mFX;
  626.     struct SGoreBoltOn        *mBoltOns;
  627.     struct SGoreChunk        *mChunks;
  628.  
  629.     struct SGoreArea        *mNext;
  630. } TGoreArea;
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642. static TGoreEffectType    *GoreEffectTypes;
  643. static TGorePieceType    *GorePieceTypes;
  644. static TGoreArea        *GoreAreas;
  645. static TGoreInfo        GoreInfo[GORE_SIDE_MAX] = 
  646. {
  647.     { "right", "r" },
  648.     { "left", "l" }
  649. };
  650.  
  651. static TGoreLocation    GoreLocations[] = 
  652. {
  653.     { "none",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  654.  
  655.     { "foot",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  656.     { "foot",        GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  657.     { "leg_upper",    GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  658.     { "leg_upper",    GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  659.     { "leg_lower",    GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  660.     { "leg_lower",    GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  661.     
  662.     { "hand",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  663.     { "hand",        GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  664.     { "arm_lower",    GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  665.     { "arm_lower",    GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  666.  
  667.     { "head",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  668.     { "torso",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  669.     
  670.     { "torso",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  671.     { "torso",        GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  672.     { "torso",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  673.     //{ "torso",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  674.     { "arm_upper",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  675.     //{ "torso",        GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  676.     { "arm_upper",        GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  677.  
  678.     { "torso",        GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  679.  
  680.     { "",            GORE_SIDE_LEFT,        GORE_SIDE_RIGHT    },
  681.  
  682.     // DEBUG ONE
  683.     { "torso",        GORE_SIDE_RIGHT,    GORE_SIDE_LEFT    },
  684.  
  685. /*
  686.     "hand_right",
  687.     "arm_lower_right",
  688.     "torso_right",
  689.     "arm_upper_right",
  690.     "leg_lower_right",
  691.     "leg_upper_right",
  692.     "hip_right",
  693.     "head_back_lower_right",
  694.     "head_back_upper_right",
  695.     "head_front_lower_right",
  696.     "head_front_mid_right",
  697.     "head_front_upper_right",
  698.     "head_side_right",
  699.     "head_right",
  700. */
  701. };
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716. static const char *CreateFinalName(const char *Input, EGoreSide *Primary, EGoreSide *Opposite, qboolean SwapIfOpposite)
  717. {
  718.     static char    output[256];
  719.     char        *outputPos;
  720.     const char    *replace = "";
  721.     EGoreSide    use = GORE_SIDE_RIGHT;
  722.     qboolean    doSwap = qfalse;
  723.     EGoreSide    save;
  724.     const char    *origInput = Input;
  725.  
  726.     outputPos = output;
  727.     while(*Input)
  728.     {
  729.         if ((*Input) == '<')
  730.         {
  731.             Input++;
  732.             if ((*Input) == 'P')
  733.             {    // default to primary
  734.                 use = *Primary;
  735.             }
  736.             else if ((*Input) == 'O')
  737.             {    // use opposite
  738.                 use = *Opposite;
  739.                 doSwap = qtrue;
  740.             }
  741.             else
  742.             {
  743.                 Com_Error(ERR_DROP, "CreateFinalName: bad input string: %s", origInput);
  744.                 break;
  745.             }
  746.  
  747.             Input++;
  748.             if ((*Input) == 'L')
  749.             {    // default to long name
  750.                 replace = GoreInfo[use].mLongName;
  751.             }
  752.             else if ((*Input) == 'S')
  753.             {    // use short name
  754.                 replace = GoreInfo[use].mShortName;
  755.             }
  756.             else
  757.             {
  758.                 Com_Error(ERR_DROP, "CreateFinalName: bad input string: %s", origInput);
  759.                 break;
  760.             }
  761.  
  762.             strcpy(outputPos, replace);
  763.             outputPos += strlen(replace);
  764.  
  765.             Input++;
  766.  
  767.             if ((*Input) != '>')
  768.             {
  769.                 Com_Error(ERR_DROP, "CreateFinalName: bad input string: %s", origInput);
  770.                 break;
  771.             }
  772.         }
  773.         else
  774.         {
  775.             *outputPos++ = *Input;
  776.         }
  777.  
  778.         Input++;
  779.     }
  780.  
  781.     *outputPos = 0;
  782.     if (SwapIfOpposite && doSwap)
  783.     {
  784.         save = *Primary;
  785.         *Primary = *Opposite;
  786.         *Opposite = save;
  787.     }
  788.  
  789.     return output;
  790. }
  791.  
  792. static TGoreArea *FindGoreZone(const char *Location, EGoreSide Primary, EGoreSide Opposite)
  793. {
  794.     TGoreArea        *gore = GoreAreas;
  795.  
  796.     while(gore)
  797.     {
  798.         if (Q_stricmp(CreateFinalName(gore->mLocation, &Primary, &Opposite, qfalse), Location) == 0)
  799.         {
  800.             return gore;
  801.         }
  802.  
  803.         gore = gore->mNext;
  804.     }
  805.  
  806.     return 0;
  807. }
  808.  
  809. static TGoreEffectType *FindGoreEffectType(const char *Name)
  810. {
  811.     TGoreEffectType    *effect = GoreEffectTypes;
  812.  
  813.     while(effect)
  814.     {
  815.         if (Q_stricmp(effect->mName, Name) == 0)
  816.         {
  817.             return effect;
  818.         }
  819.  
  820.         effect = effect->mNext;
  821.     }
  822.  
  823.     return 0;
  824. }
  825.  
  826. static TGorePieceType *FindGorePieceType(const char *Name)
  827. {
  828.     TGorePieceType    *piece = GorePieceTypes;
  829.  
  830.     while(piece)
  831.     {
  832.         if (Q_stricmp(piece->mName, Name) == 0)
  833.         {
  834.             return piece;
  835.         }
  836.  
  837.         piece = piece->mNext;
  838.     }
  839.  
  840.     return 0;
  841. }
  842.  
  843. static void CG_ParseGoreEffect(TGPGroup group)
  844. {
  845.     TGoreEffectType    *effect;
  846.     char            file[256];
  847.  
  848.     effect = (TGoreEffectType *)AllocGorePool(sizeof(*effect));
  849.     memset(effect, 0, sizeof(*effect));
  850.  
  851.     effect->mNext = GoreEffectTypes;
  852.     GoreEffectTypes = effect;
  853.  
  854.     trap_GPG_FindPairValue(group, "Name", "", effect->mName);
  855.     trap_GPG_FindPairValue(group, "File", "", file);
  856.     effect->mFXID = trap_FX_RegisterEffect(file);
  857. }
  858.  
  859. static void CG_ParseGorePiece(TGPGroup group)
  860. {
  861.     TGorePieceType    *piece;
  862.     char            file[256];
  863.  
  864.     piece = (TGorePieceType *)AllocGorePool(sizeof(*piece));
  865.     memset(piece, 0, sizeof(*piece));
  866.  
  867.     piece->mNext = GorePieceTypes;
  868.     GorePieceTypes = piece;
  869.  
  870.     trap_GPG_FindPairValue(group, "Name", "", piece->mName);
  871.     trap_GPG_FindPairValue(group, "Bolt", "", piece->mBolt);
  872.     trap_GPG_FindPairValue(group, "Model", "", file);
  873.  
  874.     if (trap_G2API_InitGhoul2Model(&piece->mG2Model, file, 0, 0, 0, 0, 0) == -1)
  875.     {    // wasn't a g2 model, so try a regular one
  876.         piece->mNormalModel = trap_R_RegisterModel(file);
  877.     }
  878. }
  879.  
  880. static TGoreEffect *CG_ParseFX(TGPGroup group)
  881. {
  882.     TGoreEffect        *effect;
  883.  
  884.     effect = (TGoreEffect *)AllocGorePool(sizeof(*effect));
  885.     memset(effect, 0, sizeof(*effect));
  886.  
  887.     trap_GPG_FindPairValue(group, "Name", "", effect->mName);
  888.     trap_GPG_FindPairValue(group, "Bolt", "", effect->mBolt);
  889.  
  890.     return effect;
  891. }
  892.  
  893. static TGoreBoltOn *CG_ParseBoltOn(TGPGroup group)
  894. {
  895.     TGoreBoltOn        *bolt;
  896.  
  897.     bolt = (TGoreBoltOn *)AllocGorePool(sizeof(*bolt));
  898.     memset(bolt, 0, sizeof(*bolt));
  899.  
  900.     trap_GPG_FindPairValue(group, "Name", "", bolt->mName);
  901.     trap_GPG_FindPairValue(group, "Bolt", "", bolt->mBolt);
  902.  
  903.     return bolt;
  904. }
  905.  
  906. static TGoreChunk *CG_ParseChunk(TGPGroup group)
  907. {
  908.     TGoreChunk        *chunk;
  909.     char            temp[256];
  910.  
  911.     chunk = (TGoreChunk *)AllocGorePool(sizeof(*chunk));
  912.     memset(chunk, 0, sizeof(*chunk));
  913.  
  914.     trap_GPG_FindPairValue(group, "Root", "", chunk->mRoot);
  915.     trap_GPG_FindPairValue(group, "Bone", "", chunk->mBone);
  916.     chunk->mSurfacesOn = AllocMultiString(trap_GPG_FindPair(group, "Surfaces_On"));
  917.     chunk->mChildrenOff = AllocMultiString(trap_GPG_FindPair(group, "Children_Off"));
  918.  
  919.     trap_GPG_FindPairValue(group, "MinForce", "40", temp);
  920.     chunk->mMinForce = atof(temp);
  921.     trap_GPG_FindPairValue(group, "MaxForce", "80", temp);
  922.     chunk->mMaxForce = atof(temp);
  923.  
  924.     return chunk;
  925. }
  926.  
  927. static void CG_ParseGoreArea(TGPGroup group)
  928. {
  929.     TGoreArea        *gore;
  930.     TGoreEffect        *effect;
  931.     TGoreBoltOn        *bolt;
  932.     TGoreChunk        *chunk;
  933.     TGPValue        flags, value;
  934.     TGPGroup        sub;
  935.     char            name[256];
  936.  
  937.     gore = (TGoreArea *)AllocGorePool(sizeof(*gore));
  938.     memset(gore, 0, sizeof(*gore));
  939.  
  940.     gore->mNext = GoreAreas;
  941.     GoreAreas = gore;
  942.  
  943.     trap_GPG_FindPairValue(group, "Location", "", gore->mLocation);
  944.  
  945.     gore->mSurfacesOff = AllocMultiString(trap_GPG_FindPair(group, "Surfaces_Off"));
  946.     gore->mSurfacesOn = AllocMultiString(trap_GPG_FindPair(group, "Surfaces_On"));
  947.     gore->mBoltsOff = AllocMultiString(trap_GPG_FindPair(group, "Bolts_Off"));
  948.     gore->mChildren = AllocMultiString(trap_GPG_FindPair(group, "Children"));
  949.  
  950.     flags = trap_GPG_FindPair(group, "Flags");
  951.     if (flags)
  952.     {
  953.         value = trap_GPV_GetList(flags);
  954.         while(value)
  955.         {
  956.             trap_GPV_GetName(value, name);
  957.             if (Q_stricmp(name, "NoChildSurfacesOn") == 0)
  958.             {
  959.                 gore->mFlags |= GORE_NO_CHILD_SURFACES_ON;
  960.             }
  961.             else if (Q_stricmp(name, "NoChildFX") == 0)
  962.             {
  963.                 gore->mFlags |= GORE_NO_CHILD_FX;
  964.             }
  965.             else if (Q_stricmp(name, "NoChildChunks") == 0)
  966.             {
  967.                 gore->mFlags |= GORE_NO_CHILD_CHUNKS;
  968.             }            
  969.             else if (Q_stricmp(name, "NoChildBoltOns") == 0)
  970.             {
  971.                 gore->mFlags |= GORE_NO_CHILD_BOLTONS;
  972.             }            
  973.             
  974.             value = trap_GPV_GetNext(value);
  975.         }
  976.     }
  977.  
  978.     sub = trap_GPG_GetSubGroups(group);
  979.     while(sub)
  980.     {
  981.         trap_GPG_GetName(sub, name);
  982.         if (Q_stricmp(name, "FX") == 0)
  983.         {
  984.             effect = CG_ParseFX(sub);
  985.             effect->mNext = gore->mFX;
  986.             gore->mFX = effect;
  987.         }
  988.         else if (Q_stricmp(name, "Chunk") == 0)
  989.         {
  990.             chunk = CG_ParseChunk(sub);
  991.             chunk->mNext = gore->mChunks;
  992.             gore->mChunks = chunk;
  993.         }
  994.         else if (Q_stricmp(name, "BoltOn") == 0)
  995.         {
  996.             bolt = CG_ParseBoltOn(sub);
  997.             bolt->mNext = gore->mBoltOns;
  998.             gore->mBoltOns = bolt;
  999.         }
  1000.  
  1001.         sub = trap_GPG_GetNext(sub);
  1002.     }
  1003. }
  1004.  
  1005. qboolean CG_ParseGore(void)
  1006. {
  1007.     TGenericParser2    GP2;
  1008.     TGPGroup        topGroup, topSubs;
  1009.     char            name[256];
  1010.  
  1011.     GP2 = trap_GP_ParseFile("ext_data/sof2.gore", qtrue, qfalse);
  1012.     if (!GP2)
  1013.     {
  1014.         return qfalse;
  1015.     }
  1016.  
  1017.     gorePoolSize = 0;
  1018.     GoreEffectTypes = 0;
  1019.     GorePieceTypes = 0;
  1020.     GoreAreas = 0;
  1021.  
  1022.     topGroup = trap_GP_GetBaseParseGroup(GP2);
  1023.     topSubs = trap_GPG_GetSubGroups(topGroup);
  1024.     while(topSubs)
  1025.     {
  1026.         trap_GPG_GetName(topSubs, name);
  1027.         if (Q_stricmp(name, "gore_area") == 0)
  1028.         {
  1029.             CG_ParseGoreArea(topSubs);
  1030.         }
  1031.         else if (Q_stricmp(name, "gore_effect") == 0)
  1032.         {
  1033.             CG_ParseGoreEffect(topSubs);
  1034.         }
  1035.         else if (Q_stricmp(name, "gore_piece") == 0)
  1036.         {
  1037.             CG_ParseGorePiece(topSubs);
  1038.         }
  1039.  
  1040.         topSubs = trap_GPG_GetNext(topSubs);
  1041.     }
  1042.  
  1043.     trap_GP_Delete(&GP2);
  1044.  
  1045.     return qtrue;
  1046. }
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064. static void CG_ProcessSurfaceList(void *model, char *surfaceList, int flags,
  1065.                                   EGoreSide Primary, EGoreSide Opposite)
  1066. {
  1067.     while(surfaceList && surfaceList[0])
  1068.     {
  1069.         if (!trap_G2API_SetSurfaceOnOff(model, 0, CreateFinalName(surfaceList, &Primary, &Opposite, qfalse), flags))
  1070.         {
  1071.  
  1072. #ifdef _DEBUG
  1073. //            Com_Printf("Missing surface '%s'\n", surfaceList);
  1074. #endif
  1075.         }
  1076.         surfaceList += strlen(surfaceList) + 1;
  1077.     }
  1078. }
  1079.  
  1080. static void CG_ProcessBoltList(void *model, char *boltList, EGoreSide Primary, EGoreSide Opposite)
  1081. {
  1082.     int        numModels;
  1083.     int        boltIndex;
  1084.     int        i;
  1085.  
  1086.     while(boltList && boltList[0])
  1087.     {
  1088.         numModels = trap_G2API_GetNumModels(model);
  1089.         boltIndex = trap_G2API_FindBoltIndex(model, 0, CreateFinalName(boltList, &Primary, &Opposite, qfalse));
  1090.         if (boltIndex != -1)
  1091.         {
  1092.             for(i=1;i<numModels;i++)
  1093.             {
  1094.                 if (trap_G2API_GetBoltIndex(model, i) == boltIndex)
  1095.                 {
  1096.                     trap_G2API_DetachG2Model(model, i);
  1097.                     trap_G2API_RemoveGhoul2Model(&model, i);
  1098.                     numModels--;
  1099.                     i--;
  1100.                 }
  1101.             }
  1102.         }
  1103.  
  1104.         boltList += strlen(boltList) + 1;
  1105.     }
  1106. }
  1107.  
  1108. static void CG_ProcessChunkChild(void *Ghoul2, char *Name,
  1109.                                  EGoreSide Primary, EGoreSide Opposite)
  1110. {
  1111.     TGoreArea        *gore;
  1112.     char            *child;
  1113.     char            finalName[256];
  1114.  
  1115.     strcpy(finalName, CreateFinalName(Name, &Primary, &Opposite, qtrue));
  1116.     gore = FindGoreZone(finalName, Primary, Opposite);
  1117.     if (!gore)
  1118.     {
  1119.         return;
  1120.     }
  1121.  
  1122.     CG_ProcessSurfaceList(Ghoul2, gore->mSurfacesOff, G2SURFACEFLAG_OFF, Primary, Opposite);
  1123.  
  1124.     child = gore->mChildren;
  1125.     while(child && child[0])
  1126.     {
  1127.         CG_ProcessChunkChild(Ghoul2, child, Primary, Opposite);
  1128.  
  1129.         child += strlen(child) + 1;
  1130.     }
  1131. }
  1132.  
  1133. static void CG_ProcessChunk(int clientNum, centity_t *cent, TGoreChunk *chunk, vec3_t Direction,
  1134.                             EGoreSide Primary, EGoreSide Opposite)
  1135. {
  1136.     localEntity_t    *le;
  1137.     refEntity_t        *re;
  1138.     int                bolt;
  1139.     char            *child;
  1140.     animation_t        *anim;
  1141.     float            animSpeed;
  1142.     int                flags=BONE_ANIM_OVERRIDE_FREEZE;
  1143.     clientInfo_t    *ci;
  1144.     mdxaBone_t        matrix;
  1145.     qboolean        boltMatrixOK = qfalse;;
  1146.  
  1147.     le = CG_AllocLocalEntity();
  1148.     re = &le->refEntity;
  1149.  
  1150.     le->leType = LE_GIB;
  1151.     le->startTime = cg.time;
  1152.     le->endTime = le->startTime + BODY_SINK_DELAY + BODY_SINK_TIME;
  1153.     le->leFlags = LEF_TUMBLE;
  1154.     le->bounceFactor = 0.2f;
  1155.     re->radius = 50;
  1156.     re->renderfx = RF_MINLIGHT;
  1157.  
  1158.     VectorSet ( re->modelScale, 1, 1, 1 );
  1159.  
  1160.     AxisCopy( axisDefault, re->axis );
  1161.  
  1162.     le->pos.trType = TR_GRAVITY;
  1163.     VectorMA ( vec3_origin, irand ( chunk->mMinForce * 2, chunk->mMaxForce * 2), Direction, le->pos.trDelta );
  1164.     le->pos.trDelta[2] = flrand ( 100, 150 );
  1165.     le->pos.trTime = cg.time;
  1166.  
  1167.     le->angles.trType = TR_LINEAR_STOP;
  1168.     VectorClear(le->angles.trBase);
  1169.     le->angles.trBase[YAW] = crandom() * 15;
  1170.     le->angles.trDelta[0] = 0.0; // crandom();
  1171.     le->angles.trDelta[YAW] = crandom() * 15 - 7;
  1172.     le->angles.trDelta[2] = 0.0; // crandom();
  1173.     le->angles.trDuration = BODY_SINK_DELAY + BODY_SINK_TIME;
  1174.     le->angles.trTime = cg.time;
  1175.  
  1176.     le->zOffset = 26.0;
  1177.  
  1178.     // ghoul stuff to do limbs
  1179.     if (!cent->ghoul2)
  1180.     {
  1181.         Com_Error(ERR_DROP, "CG_ProcessChunk invalid g2 pointer for client %d\n", clientNum);
  1182.     }
  1183.  
  1184.     trap_G2API_DuplicateGhoul2Instance(cent->ghoul2, &re->ghoul2);
  1185.     if (!re->ghoul2)
  1186.     {    // whoa, that surface caused our model to go away???
  1187.         CG_FreeLocalEntity(le);
  1188.         return;
  1189.     }
  1190.  
  1191.     trap_G2API_SetRootSurface(&re->ghoul2, 0, CreateFinalName(chunk->mRoot, &Primary, &Opposite, qfalse));
  1192.  
  1193.     bolt = trap_G2API_AddBolt(cent->ghoul2, 0, CreateFinalName(chunk->mBone, &Primary, &Opposite, qfalse));
  1194.     if (bolt != -1)
  1195.     {
  1196.         boltMatrixOK = trap_G2API_GetBoltMatrix(cent->ghoul2, 0, bolt, &matrix, cent->lerpAngles, 
  1197.             cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale);
  1198.     }
  1199.  
  1200.     if (bolt == -1 || !boltMatrixOK)
  1201.     {
  1202.         return;
  1203.     }
  1204.  
  1205.     matrix.matrix[0][3] = cent->lerpOrigin[0];
  1206.     matrix.matrix[1][3] = cent->lerpOrigin[1];
  1207.     matrix.matrix[2][3] = cent->lerpOrigin[2];
  1208.  
  1209.     le->pos.trBase[0] = re->origin[0] = matrix.matrix[0][3];
  1210.     le->pos.trBase[1] = re->origin[1] = matrix.matrix[1][3];
  1211.     le->pos.trBase[2] = re->origin[2] = matrix.matrix[2][3];
  1212.  
  1213.     bolt = trap_G2API_AddBolt(re->ghoul2, 0, CreateFinalName(chunk->mBone, &Primary, &Opposite, qfalse));
  1214.     trap_G2API_SetNewOrigin(re->ghoul2, 0, bolt);
  1215.     
  1216.     ci = &cgs.clientinfo[clientNum];
  1217.     anim = &ci->animations[cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT];
  1218.     animSpeed = 50.0f / anim->frameLerp;
  1219.  
  1220.     trap_G2API_SetBoneAnim(re->ghoul2, 0, "model_root", anim->firstFrame + anim->numFrames - 1, anim->firstFrame + anim->numFrames, flags, animSpeed, cg.time, -1, 0);
  1221.     trap_G2API_SetBoneAnim(re->ghoul2, 0, "lower_lumbar", anim->firstFrame + anim->numFrames - 1, anim->firstFrame + anim->numFrames, flags, animSpeed, cg.time, -1, 0);
  1222.  
  1223.     CG_ProcessSurfaceList(re->ghoul2, chunk->mSurfacesOn, 0, Primary, Opposite);
  1224.  
  1225.     child = chunk->mChildrenOff;
  1226.     while(child && child[0])
  1227.     {
  1228.         CG_ProcessChunkChild(re->ghoul2, child, Primary, Opposite);
  1229.  
  1230.         child += strlen(child) + 1;
  1231.     }
  1232. }
  1233.  
  1234. static void CG_ProcessBoltOn(int clientNum, centity_t *cent, TGoreBoltOn *bolton,
  1235.                             EGoreSide Primary, EGoreSide Opposite)
  1236. {
  1237.     TGorePieceType    *piece = FindGorePieceType(bolton->mName);
  1238.     const char        *boltPosition;
  1239.     int                pieceIndex;
  1240.     int                boltIndex;
  1241.  
  1242.     if (!piece)
  1243.     {
  1244.         return;
  1245.     }
  1246.  
  1247.     if (piece->mG2Model)
  1248.     {
  1249.         boltPosition = bolton->mBolt;
  1250.         if (!boltPosition[0])
  1251.         {
  1252.             boltPosition = piece->mBolt;
  1253.         }
  1254.  
  1255.         pieceIndex = trap_G2API_CopySpecificGhoul2Model(piece->mG2Model, 0, cent->ghoul2, -1);
  1256.         if (pieceIndex != -1)
  1257.         {
  1258.             boltIndex = trap_G2API_AddBolt(cent->ghoul2, 0, CreateFinalName(boltPosition, &Primary, &Opposite, qfalse));
  1259.             if (boltIndex != -1)
  1260.             {
  1261.                 trap_G2API_AttachG2Model(cent->ghoul2, pieceIndex, cent->ghoul2, boltIndex, 0);
  1262.             }
  1263.         }
  1264.     }
  1265. }
  1266.  
  1267. static void CG_ProcessGore(int clientNum, centity_t *cent, const char *Location, unsigned Flags,
  1268.                            vec3_t Direction, EGoreSide Primary, EGoreSide Opposite)
  1269. {
  1270.     TGoreArea        *gore;
  1271.     TGoreEffect        *fx;
  1272.     TGoreChunk        *chunk;
  1273.     TGoreBoltOn        *bolton;
  1274.     char            *children;
  1275.     int                bolt;
  1276.     mdxaBone_t        matrix;
  1277.     qboolean        boltMatrixOK;
  1278.     vec3_t            origin;
  1279.     TGoreEffectType *effect;
  1280.     char            finalName[256];
  1281.  
  1282.     strcpy(finalName, CreateFinalName(Location, &Primary, &Opposite, qtrue));
  1283.     gore = FindGoreZone(finalName, Primary, Opposite);
  1284.     if (!gore)
  1285.     {
  1286.         return;
  1287.     }
  1288.  
  1289.     if (!(Flags & GORE_CHILD) || !(Flags & GORE_NO_CHILD_FX) )
  1290.     {
  1291.         fx = gore->mFX;
  1292.         while(fx)
  1293.         {
  1294.             effect = FindGoreEffectType(fx->mName);
  1295.             if (effect)
  1296.             {
  1297.                 bolt = trap_G2API_AddBolt(cent->ghoul2, 0, CreateFinalName(fx->mBolt, &Primary, &Opposite, qfalse));
  1298.                 if (bolt != -1)
  1299.                 {
  1300.                     vec3_t axis[3];
  1301.                     int boltInfo;
  1302.  
  1303.                     boltMatrixOK = trap_G2API_GetBoltMatrix(cent->ghoul2, 0, bolt, &matrix, cent->lerpAngles, 
  1304.                                             cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale);                    
  1305.                     axis[0][0] = matrix.matrix[0][0];
  1306.                     axis[0][1] = matrix.matrix[1][0];
  1307.                     axis[0][2] = matrix.matrix[2][0];
  1308.                     axis[1][0] = matrix.matrix[0][1];
  1309.                     axis[1][1] = matrix.matrix[1][1];
  1310.                     axis[1][2] = matrix.matrix[2][1];
  1311.                     axis[2][0] = matrix.matrix[0][2];
  1312.                     axis[2][1] = matrix.matrix[1][2];
  1313.                     axis[2][2] = matrix.matrix[2][2];
  1314.                      origin[0] = matrix.matrix[0][3];
  1315.                      origin[1] = matrix.matrix[1][3];
  1316.                      origin[2] = matrix.matrix[2][3];
  1317.  
  1318.  
  1319.                     boltInfo    =  (( 0/*modelnum*/ & MODEL_AND  ) << MODEL_SHIFT  ); 
  1320.                     boltInfo    |= (( bolt  & BOLT_AND   ) << BOLT_SHIFT   );
  1321.                     boltInfo    |= (( cent->currentState.number   & ENTITY_AND ) << ENTITY_SHIFT );
  1322.  
  1323.                     trap_FX_PlayEntityEffectID( effect->mFXID, origin, axis, boltInfo, -1, -1, -1);
  1324. /*                    boltMatrixOK = trap_G2API_GetBoltMatrix(cent->ghoul2, 0, bolt, &matrix, cent->lerpAngles, 
  1325.                         cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale);
  1326.                     if (boltMatrixOK)
  1327.                     {
  1328.                          origin[0] = matrix.matrix[0][3];
  1329.                          origin[1] = matrix.matrix[1][3];
  1330.                          origin[2] = matrix.matrix[2][3];
  1331.                         trap_FX_PlayEffectID(effect->mFXID, origin, Direction, -1, -1 );
  1332.                     }
  1333. */                }
  1334.             }
  1335.  
  1336.             fx = fx->mNext;
  1337.         }
  1338.     }
  1339.  
  1340.     if (!(Flags & GORE_CHILD) || !(Flags & GORE_NO_CHILD_CHUNKS) )
  1341.     {
  1342.         chunk = gore->mChunks;
  1343.         while(chunk)
  1344.         {
  1345.             CG_ProcessChunk(clientNum, cent, chunk, Direction, Primary, Opposite);
  1346.  
  1347.             chunk = chunk->mNext;
  1348.         }
  1349.     }
  1350.  
  1351.     if (!(Flags & GORE_CHILD) || !(Flags & GORE_NO_CHILD_BOLTONS) )
  1352.     {
  1353.         bolton = gore->mBoltOns;
  1354.         while(bolton)
  1355.         {
  1356.             CG_ProcessBoltOn(clientNum, cent, bolton, Primary, Opposite);
  1357.  
  1358.             bolton = bolton->mNext;
  1359.         }
  1360.     }
  1361.  
  1362.     CG_ProcessSurfaceList(cent->ghoul2, gore->mSurfacesOff, G2SURFACEFLAG_OFF, Primary, Opposite);
  1363.     if (!(Flags & GORE_CHILD) || !(Flags & GORE_NO_CHILD_SURFACES_ON) )
  1364.     {    // children with no gore from the parents shouldn't do this
  1365.         CG_ProcessSurfaceList(cent->ghoul2, gore->mSurfacesOn, 0, Primary, Opposite);
  1366.     }
  1367.     CG_ProcessBoltList(cent->ghoul2, gore->mBoltsOff, Primary, Opposite);
  1368.  
  1369.     children = gore->mChildren;
  1370.     while(children && children[0])
  1371.     {
  1372.         CG_ProcessGore(clientNum, cent, children, gore->mFlags | Flags | GORE_CHILD, Direction, Primary, Opposite);
  1373.         children += strlen(children) + 1;
  1374.     }
  1375. }
  1376.  
  1377.  
  1378. void CG_ApplyGore(int clientNum, centity_t *cent, int hitLocation, vec3_t Direction)
  1379. {
  1380.     TGoreLocation    *Location = 0;
  1381.     const char        *dg, *token;
  1382.     char            area[256];
  1383.     EGoreSide        side;
  1384.     int                i;
  1385.  
  1386.     // Gore locked?
  1387.     if ( cg_lockSever.integer )
  1388.     {
  1389.         return;
  1390.     }
  1391.  
  1392.     dg = cg_DebugGore.string;
  1393.     if (dg[0])
  1394.     {
  1395.         strcpy(area, COM_Parse(&dg));
  1396.         token = COM_Parse(&dg);
  1397.         for(side=0;side<GORE_SIDE_MAX;side++)
  1398.         {
  1399.             if (Q_stricmp(GoreInfo[side].mLongName, token) == 0 ||
  1400.                 Q_stricmp(GoreInfo[side].mShortName, token) == 0)
  1401.             {
  1402.                 break;
  1403.             }
  1404.         }
  1405.         for(i=0;i<HL_DEBUG;i++)
  1406.         {
  1407.             if (Q_stricmp(GoreLocations[i].mPublicName, area) == 0 &&
  1408.                 GoreLocations[i].mPrimarySide == side)
  1409.             {
  1410.                 Location = &GoreLocations[i];
  1411.                 break;
  1412.             }
  1413.         }
  1414.     }
  1415.  
  1416.     if (!Location)
  1417.     {
  1418.         if (hitLocation < 0 || hitLocation >= (sizeof(GoreLocations) / sizeof(struct SGoreLocation)))
  1419.         {
  1420.             Com_Error( ERR_DROP, "CG_ApplyGore: invalid hit location %d\n", hitLocation);
  1421.             return;
  1422.         }
  1423.         Location = &GoreLocations[hitLocation];    
  1424.     }
  1425.     else
  1426.     {
  1427.         // just so that I don't have to keep restarting the game to change the file
  1428.         CG_ParseGore();
  1429.  
  1430.         Com_Printf ( "GORE:  Applying gore to location '%s'\n", Location->mPublicName );
  1431.     }
  1432.  
  1433.     CG_ProcessGore(clientNum, cent, Location->mPublicName, 0, Direction, Location->mPrimarySide, Location->mOppositeSide);
  1434. }
  1435.  
  1436. void CG_ShutdownGore(void)
  1437. {
  1438.     TGorePieceType    *piece = GorePieceTypes;
  1439.  
  1440.     while(piece)
  1441.     {
  1442.         if (piece->mG2Model)
  1443.         {
  1444.             trap_G2API_CleanGhoul2Models(&piece->mG2Model);
  1445.         }
  1446.         piece = piece->mNext;
  1447.     }
  1448.  
  1449. }
  1450.  
  1451.  
  1452.  
  1453.